package org.angelica.modules.account.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import org.angelica.common.AppConstant;
import org.angelica.core.annotation.TargetDataSource;
import org.angelica.core.common.AccessToken;
import org.angelica.core.datasource.DataSourceNames;
import org.angelica.enums.RedisKeyEnum;
import org.angelica.exception.ServiceErrorEnum;
import org.angelica.exception.ServiceException;
import org.angelica.modules.account.dao.AccUserDao;
import org.angelica.modules.account.entity.AccUserDO;
import org.angelica.modules.account.query.AccUserQuery;
import org.angelica.modules.account.service.AccUserService;
import org.angelica.utils.json.JacksonUtil;
import org.angelica.utils.security.BcryptUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 管理员表 服务实现类
 * </p>
 *
 * @author aizhimin
 * @since 2019-05-12
 */
@Service
public class AccUserServiceImpl extends ServiceImpl<AccUserDao, AccUserDO> implements AccUserService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public AccessToken login(String username, String password) {
        AccUserDO accUserDO = this.getOne(new QueryWrapper<AccUserDO>()
                .select("id","username","password")
                .eq("username",username));
        if(accUserDO == null){
            throw new ServiceException(ServiceErrorEnum.USER_NOT_EXIST);
        }
        if(!BcryptUtil.matchPassword(password,accUserDO.getPassword())){
            throw new ServiceException(ServiceErrorEnum.PASSWORD_ERROR);
        }
        return AccessToken.buildAccessToken(accUserDO.getId(), AppConstant.JWT_SECRET,AppConstant.JWT_ISUSER);
    }

    @Override
    public AccessToken regist(String username, String password, String nickname) {
        AccUserDO accUserDO = this.getOne(new QueryWrapper<AccUserDO>()
                .select("id","username","password")
                .eq("username",username));
        if(accUserDO != null){
            throw new ServiceException(ServiceErrorEnum.USER_HAS_REGISTED);
        }
        accUserDO = AccUserDO.builder()
                .username(username)
                .password(BcryptUtil.encodePassword(password))
                .nickname(nickname)
                .gmtCreate(Calendar.getInstance().getTime())
                .build();
        this.save(accUserDO);
        return AccessToken.buildAccessToken(accUserDO.getId(),AppConstant.JWT_SECRET,AppConstant.JWT_ISUSER);
    }

    @Override
    public List<String> listMyPermission(Long currentUserId) {

        String perms = stringRedisTemplate.opsForValue().get(RedisKeyEnum.PERMISSION.getPrefix() + currentUserId);
        if(StringUtils.isBlank(perms)){
            List<String> permList = this.baseMapper.listMyPermission(currentUserId);
            //设置到redis缓存
            stringRedisTemplate.opsForValue().set(RedisKeyEnum.PERMISSION.getPrefix() + currentUserId,
                    JacksonUtil.nonEmptyMapper().toJson(permList),
                    RedisKeyEnum.PERMISSION.getExpiredTime(), TimeUnit.SECONDS);
            return permList;
        }

        return JacksonUtil.nonEmptyMapper().fromJson(perms,new TypeReference<List<String>>(){});
    }

    /**
     *
     * 如果需要指定数据源，添加注解：@TargetDataSource(DataSourceNames.DLA_DS)
     * @param accUserQuery
     * @return
     */
    @Override
    public IPage<AccUserDO> listAccUser(AccUserQuery accUserQuery) {
        return this.baseMapper.listAccUser(accUserQuery.buildPage(),accUserQuery);
    }
}
